package cqrtplm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.pdm.common.model.dto.search.SearchAttributeDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchAttributeGroupDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchConditionDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchTypeDTO;
import com.hustcad.plm.pdm.common.model.vo.search.ResultEntityVO;
import com.hustcad.plm.pdm.common.model.vo.search.SearchAttributeVO;
import com.hustcad.plm.pdm.common.service.impl.search.TyplmCommonSearchServiceImpl;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.file.service.TyFileHandleService;
import com.hustcad.plm.pdm.file.service.impl.TyplmFileServiceImpl;
import com.hustcad.plm.pdm.filevault.model.vo.FileDataVO;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.flowbusiness.model.entity.WorkFlowObjectPackage;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService;
import com.hustcad.plm.pdm.preview.config.PreviewFactory;
import com.hustcad.plm.pdm.preview.dto.PreviewFileInfoDTO;
import com.hustcad.plm.pdm.preview.dto.PreviewParamDTO;
import com.hustcad.plm.pdm.preview.dto.PreviewPathDTO;
import com.hustcad.plm.pdm.preview.service.TyplmPreviewFileService;
import com.hustcad.plm.pdm.preview.service.api.TyplmPreviewFileApiService;
import com.hustcad.plm.pdm.preview.util.TyplmFileDownloadUtils;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.exception.MessageException;
import com.ty.basic.exception.message.SystemErrorCodeEnum;
import com.ty.basic.handler.exceptionhandler.exception.ResponseCodeEnum;
import com.ty.basic.handler.exceptionhandler.exception.TyException;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.util.EntityBaseUtil;
import com.ty.basic.vo.AttributeVO;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.constant.RTTableTypeConstant;
import cqrtplm.constant.RouteConstant;
import cqrtplm.dto.CadDataDTO;
import cqrtplm.dto.ProblemReportDTO;
import cqrtplm.entity.OnlineAnnotationDO;
import cqrtplm.mapper.CADDocumentMapper;
import cqrtplm.mapper.OnlineAnnotationMapper;
import cqrtplm.mapper.RTTypeClassMapper;
import cqrtplm.service.GetCADDocumentService;
import cqrtplm.service.RTChangeService;
import cqrtplm.vo.CadDataVO;
import cqrtplm.vo.OnlineAnnotationVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.XML;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@Service
@Slf4j
public class GetCADDocumentServiceImpl implements GetCADDocumentService {
    // 提取普通content属性
    private static final String CONTENT_XPATH = "//@content";
    // 提取JSON中的text字段
    private static final Pattern JSON_TEXT_PATTERN = Pattern.compile("\"text\":\"(.*?)\"");
    @Resource
    private TyplmFileServiceImpl typlmFileService;
    @Resource
    private TyFileHandleService fileHandleService;
    @Resource
    private TyplmCommonSearchServiceImpl typlmCommonSearchService;
    @Resource
    private TyplmPreviewFileService typlmPreviewFileService;
    @Resource
    private RTTypeClassMapper typeMapper;
    @Resource
    private CADDocumentMapper cadDocumentMapper;
    @Value("${file.default.dir}")
    private String fileExportDefaultDir;
    @Resource
    private RTChangeService changeService;
    @Resource
    TyplmFileDownloadUtils typlmFileDownloadUtils;
    @Resource
    private TyplmUserService typlmUserService;
    @Resource
    private OnlineAnnotationMapper onlineAnnotationMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private TyplmWorkFlowContainerService typlmWorkFlowContainerService;
    @Resource
    private TyplmAttributeValueService typlmAttributeValueService;

    @Override
    public void getTechnologyDocumentByNumber(CadDataDTO cadDataDTO, HttpServletResponse response) {

        String fileVersion = cadDataDTO.getFileVersion();
        String type = getType(cadDataDTO.getObjType());
        List<FileDataVO> fileList ;
        String remark = "";
        if(type.contains(TableTypeConstrant.TY_DOC_OTYPE)){
            //获取DOC对象
            String oid = cadDocumentMapper.getLastDocByNumber(cadDataDTO.getFileCode(), fileVersion);
            if(StringUtils.isEmpty(oid) || StringUtils.isBlank(oid)){
                throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("未查询到文档对象");
            }
            IdentifierEntity entity = new IdentifierEntity(new BigInteger(oid),TableTypeConstrant.TY_DOC_OTYPE);
            fileList = this.fileHandleService.getFileListByEntity(entity);
            remark = "2";
        }else if(type.contains(TableTypeConstrant.TY_CADDOC_OTYPE)){
            //获取CAD对象
            String oid = cadDocumentMapper.getLastCADByNumber(cadDataDTO.getFileCode(), fileVersion);
            IdentifierEntity entity = new IdentifierEntity(new BigInteger(oid),TableTypeConstrant.TY_CADDOC_OTYPE);
            fileList = this.fileHandleService.getFileListByEntity(entity);
            if(type.contains("三维数模")){
                remark = "3";
            }else if(type.contains("二维图纸")){
                remark = "2";
            }
        }else {
            throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("类型"+ type + "不支持");
        }
        if(CollUtil.isEmpty(fileList)){
            throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("未查询到电子文件");
        }
        downloadFile(response, fileList,cadDataDTO.getFileType() ,remark);
    }

    private void downloadFile(HttpServletResponse response, List<FileDataVO> fileList ,String fileType, String remark) {
        List<BigInteger> fileOidList = new ArrayList<>();
        if (fileList.size() > 1) {
            log.info("多个附件");
        } else if (fileList.size() == 1) {
            List<FileDataVO> pdfFiles = null;
            FileDataVO fileDataVO = fileList.get(0);
            if ("0".equals(fileType)) { // 0代表源文件 1代表轻量化文件
                fileOidList.add(new BigInteger(fileDataVO.getFileID()));
            } else if ("1".equals(fileType)) {

                if ("2".equals(remark)) {
                    pdfFiles = fileDataVO.getFileDataVOList().stream().filter(item -> "PDF".equalsIgnoreCase(item.getFileName().split("\\.")[1])).collect(
                            Collectors.toList());
                }else if("3".equals(remark)){
                    pdfFiles = fileDataVO.getFileDataVOList().stream()
                            .filter(item -> {
                                String fileName = item.getFileName();
                                return fileName.toLowerCase().endsWith(".iwp") || fileName.toLowerCase().endsWith(".iwa");
                            })
                            .collect(Collectors.toList());
                }
                if (CollUtil.isEmpty(pdfFiles)) {
                    throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("轻量化文件不存在无法下载");
                }
                fileOidList.add(new BigInteger(pdfFiles.get(0).getFileID()));
            } else if ("2".equals(fileType)) {
                if ("2".equals(remark)) {
                    pdfFiles = fileDataVO.getFileDataVOList().stream().filter(item -> "SVGZ".equalsIgnoreCase(item.getFileName().split("\\.")[1])).collect(
                            Collectors.toList());
                }
                if (CollUtil.isEmpty(pdfFiles)) {
                    throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("轻量化文件不存在无法下载");
                }
                fileOidList.add(new BigInteger(pdfFiles.get(0).getFileID()));
            }
            this.typlmFileService.download(fileOidList, response);
        }
    }

    /**
     * 通过技术文档名称获取文件流
     *
     * @param cadDataDTO
     * @param response
     */
    @Override
    public void getTechnologyDocumentByName(CadDataDTO cadDataDTO, HttpServletResponse response) {
        List<CadDataVO> conditionDTO = getConditionDTO(cadDataDTO);
        if(CollUtil.isEmpty(conditionDTO)){
            log.info("文档对象为空");
            return;
        }
        IdentifierEntity identifierEntity = new IdentifierEntity();
        identifierEntity.setOid(new BigInteger(conditionDTO.get(0).getOid()));
        log.info("identifierEntity OID===:{}", identifierEntity.getOid());
        String type = getType(cadDataDTO.getObjType());
        String remark = "";
        if(type.contains(TableTypeConstrant.TY_DOC_OTYPE)){
            identifierEntity.setOtype(TableTypeConstrant.TY_DOC_OTYPE);
            remark = "2";
        }else if(type.contains(TableTypeConstrant.TY_CADDOC_OTYPE)){
            identifierEntity.setOtype(TableTypeConstrant.TY_CADDOC_OTYPE);
            if(type.contains("三维数模")){
                remark = "3";
            }else if(type.contains("二维图纸")){
                remark = "2";
            }
        }
        List<FileDataVO> fileListByEntity = this.fileHandleService.getFileListByEntity(identifierEntity);
        log.info(fileListByEntity.toString());
        log.info("SIZE===:{}", fileListByEntity.size());

        downloadFile(response, fileListByEntity,cadDataDTO.getFileType(),remark);
    }

    /**
     * 模糊匹配技术文档，
     * @param cadDataDTO
     * @return
     */
    @Override
    public List<CadDataVO> getConditionDTO(CadDataDTO cadDataDTO) {
        log.info("获取文档列表入参 ==> cadDataDTO:{}",cadDataDTO);
        log.info("获取文档列表 ==>  开始");
        String fileName = cadDataDTO.getFileName();
        String name = "";
        if (StringUtils.isNotBlank(fileName) && fileName.contains("*")) {
            String[] split = fileName.split("\\*");
            cadDataDTO.setFileName(split[0]);
            name = split[1];
        }
        SearchConditionDTO conditionDTO = buildSearchConditionDTO(cadDataDTO);
        PageInfo<ResultEntityVO> resultEntityVOPageInfo = this.typlmCommonSearchService.queryByConditionForPage(
                conditionDTO);
        List<IdentifierEntity> entityList = new ArrayList<>();
        Map<IdentifierEntity, CadDataVO> map = new HashMap<>();
        for(ResultEntityVO resultEntityVO :resultEntityVOPageInfo.getList()) {
            CadDataVO vo = new CadDataVO();
            if(!"c/i".equals(resultEntityVO.getLockstateinfo())){
                continue;
            }
            if(StringUtils.isNotBlank(name)){
                String voName = resultEntityVO.getName();
                if(!voName.contains(name)){
                    continue;
                }
            }
            if (TableTypeConstrant.TY_DOC_OTYPE.equals(
                    resultEntityVO.getOtype()) || TableTypeConstrant.TY_CADDOC_OTYPE.equals(
                    resultEntityVO.getOtype())) {
                IdentifierEntity entity = resultEntityVO.getIdentifierRef();
                entityList.add(entity);
                vo.setNumber(resultEntityVO.getObjectNumber());
                vo.setName(resultEntityVO.getName());
                vo.setVersion(resultEntityVO.getVersion() + "." + resultEntityVO.getIterationid());
                vo.setCreateDate(String.valueOf(resultEntityVO.getCreatestamp()));
                vo.setLastModifiedDate(String.valueOf(resultEntityVO.getUpdatestamp()));
                vo.setCreateBy(resultEntityVO.getCreatorFullName());
                vo.setUpdateBy(resultEntityVO.getUpdatorFullName());
                vo.setOid(String.valueOf(resultEntityVO.getOid()));
                map.put(entity, vo);
            }
        }

        // 获取文件列表
        Map<IdentifierEntity, List<FileDataVO>> identifierEntityListMap = this.fileHandleService.batchGetFileListByEntity(
                entityList);
        // 更新 CadDataVO 对象的文件信息
        for (Map.Entry<IdentifierEntity, List<FileDataVO>> entry : identifierEntityListMap.entrySet()) {
            IdentifierEntity key = entry.getKey();
            if (map.containsKey(key)) {
                CadDataVO vo = map.get(key);
                List<FileDataVO> value = entry.getValue();
                if (CollUtil.isNotEmpty(value)) {
                    FileDataVO fileDataVO = value.get(0);
                    vo.setFileSize(fileDataVO.getFileSize());
                    vo.setFileExtension(fileDataVO.getFileName().split("\\.")[1]);
                    vo.setFileName(fileDataVO.getFileName());
                }
            }
        }

        log.info("获取文档列表 ==>  结束");
        return new ArrayList<>(map.values());
    }

    private SearchConditionDTO buildSearchConditionDTO(CadDataDTO cadDataDTO) {
        SearchConditionDTO conditionDTO = new SearchConditionDTO();
        List<SearchTypeDTO> typeDTOS = new ArrayList<>();
        SearchTypeDTO searchTypeDTO = new SearchTypeDTO();
        String objType = cadDataDTO.getObjType();
        String type = getType(objType);
        searchTypeDTO.setTypeInthid(type);
        BigInteger typeOid = typeMapper.queryTypeOidByName(type);
        if(typeOid == null){
            throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("文档类型不存在");
        }
        searchTypeDTO.setTypeOid(typeOid);
        typeDTOS.add(searchTypeDTO);
        conditionDTO.setTypeList(typeDTOS);
        conditionDTO.setPageNum(1);
        conditionDTO.setPageSize(500);
        conditionDTO.setNeedThumbnailFile(true);
        conditionDTO.setNeedCount(true);
        if(StringUtils.isNotBlank(cadDataDTO.getFileName())){
            conditionDTO.setKeyword(cadDataDTO.getFileName());
        }else if(StringUtils.isNotBlank(cadDataDTO.getFileCode())){
            conditionDTO.setKeyword(cadDataDTO.getFileCode());
        }
        conditionDTO.setConditionJoint(RouteConstant.AND);
        SearchAttributeGroupDTO groupDTO = new SearchAttributeGroupDTO();
        groupDTO.setConditionJoint(RouteConstant.OR);
        SearchAttributeDTO attributeDTO = new SearchAttributeDTO();
        attributeDTO.setPropertyName("version");
        attributeDTO.setPropertyValue(cadDataDTO.getFileVersion());
        attributeDTO.setSymbol("=");
        attributeDTO.setPropertyType("String");
        attributeDTO.setConstraintInfo(new SearchAttributeVO("", "String", "version", "", new ArrayList<>()));
        List<SearchAttributeDTO> attributeDTOS = new ArrayList<>();
        attributeDTOS.add(attributeDTO);
        groupDTO.setConditions(attributeDTOS);

        List<SearchAttributeGroupDTO> conditionGroups = new ArrayList<>();
        conditionGroups.add(groupDTO);
        conditionDTO.setConditionGroups(conditionGroups);
        return conditionDTO;
    }

    private String getType(String objType) {
        String type = "";
        if(objType.contains("|")){
            String[] types = objType.split("\\|");
            if("CAD".equals(types[0])){
                if("AutoCAD".equals(types[1]) || "UG工程图".equals(types[1])){
                    type = TableTypeConstrant.TY_CADDOC_OTYPE + "|"+ "二维图纸|" + types[1];
                } else if("UG".equals(types[1])){
                    type = TableTypeConstrant.TY_CADDOC_OTYPE + "|"+ "三维数模|" + types[1];
                } else {
                    throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("objType参数异常");
                }

            }else {
                type = TableTypeConstrant.TY_DOC_OTYPE + "|"+ types[1];
            }
        }else {
            throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("objType参数异常");
        }
        return type;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<OnlineAnnotationVO> refreshOnlineAnnotation(HttpServletRequest request, HttpServletResponse response, ProblemReportDTO dto) {
        File tempZipFile = null;

        List<String> oidS = onlineAnnotationMapper.selectOidByObjOid(dto.getObjId());
        PreviewParamDTO paramDTO = typlmPreviewFileService.buildPreviewFileParameter(new BigInteger(dto.getObjId()),
                                                                                         dto.getObjType(),
                                                                                         dto.getFileId(),
                                                                                         dto.getPreviewFileName());
        try {
            Optional.ofNullable(request.getHeader("CadStructRule")).ifPresent(paramDTO::setCadStructRule);
            Map<String, InputStream> fileMap = getFileMap(request, paramDTO);
            log.info("filemap ==fileMap =>>>>:{}", fileMap);
            List<OnlineAnnotationVO> list = new ArrayList<>();
            for (Map.Entry<String, InputStream> entry : fileMap.entrySet()) {
                String zipName = entry.getKey();
                InputStream value = entry.getValue();
                tempZipFile = new File(fileExportDefaultDir + File.separator + zipName);
                // 确保父目录存在
                File parentDir = tempZipFile.getParentFile();
                if (parentDir != null && !parentDir.exists()) {
                    parentDir.mkdirs(); // 创建所有必要的父目录
                }
                try (InputStream is = value) {
                    Files.copy(is, tempZipFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("写入文件失败: " + tempZipFile.getAbsolutePath(), e);
                }
                //解压zip文件
                List<MultipartFile> files = extractZipToMultipartFiles(tempZipFile);
                String fileExtension = "";

                for (MultipartFile file : files) {
                    String fileName = file.getName();
                    int dotIndex = fileName.lastIndexOf('.');
                    if (dotIndex > 0) {
                        fileExtension = fileName.substring(dotIndex + 1);
                    }
                    if (StringUtils.isNotBlank(fileExtension) && "xml".equals(fileExtension)) {
                        String strXml = "";
                        try (InputStream inputStream = file.getInputStream()) {
                            strXml = IOUtils.toString(inputStream, "UTF-8");
                        }
                        JSONObject jsonObject = XML.toJSONObject(strXml);
                        Object o = jsonObject.getJSONObject("WebPdfXmlRoot").getJSONObject("Annotations").get("Annotation");
                        if (o instanceof JSONObject) {
                            JSONObject json = (JSONObject) o;
                            processSingleJsonObject(json, dto, list, oidS);
                        } else if (o instanceof JSONArray) {
                            JSONArray array = (JSONArray) o;
                            for (Object object : array) {
                                JSONObject json = (JSONObject) object;
                                processSingleJsonObject(json, dto, list, oidS);
                            }
                        }
                    }
                }
            }
            if(CollUtil.isNotEmpty(oidS)){
                for (String oid : oidS) {
                    onlineAnnotationMapper.deleteByPrimaryKey(oid);
                    onlineAnnotationMapper.deleteFileLikeByOid(oid);
                }
            }
            return OnlineAnnotationVO.buildVO( list);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            tempZipFile.delete();
        }
    }


    private void processSingleJsonObject(JSONObject json, ProblemReportDTO dto, List<OnlineAnnotationVO> list, List<String> oidS) {
        String user = json.getString("name");
        String text = json.getString("content");
        String guid = json.getString("guid");
        OnlineAnnotationDO annotationDO = buildOnlineAnnotationDO(dto, user, text, guid);
        OnlineAnnotationDO existing = onlineAnnotationMapper.selectByPrimaryKey(guid);
        oidS.remove(guid);
        if (existing != null) {
            OnlineAnnotationDO.fillCommonFieldForUpdate(existing, new Date());
            onlineAnnotationMapper.updateByPrimaryKey(existing);
        } else {
            onlineAnnotationMapper.insert(annotationDO);
        }

        List<OnlineAnnotationVO> vos = onlineAnnotationMapper.selectByOid(guid);
        if (CollUtil.isNotEmpty(vos)) {
            list.addAll(vos);
        }
    }

    private OnlineAnnotationDO buildOnlineAnnotationDO(ProblemReportDTO dto, String user, String text, String guid) {
        OnlineAnnotationDO onlineAnnotationDO = new OnlineAnnotationDO();
        onlineAnnotationDO.setOid(guid);
        onlineAnnotationDO.setOtype(RTTableTypeConstant.TYPE_ONLINE_ANNOTATION);
        onlineAnnotationDO.setCreatorFullName(user);
        onlineAnnotationDO.setCreatorOid(String.valueOf(TyAccountContext.getUser().getOid()));
        onlineAnnotationDO.setDescription(text);
        onlineAnnotationDO.setBoid(dto.getObjId());
        onlineAnnotationDO.setBotype(dto.getObjType());
        OnlineAnnotationDO.fillCommonFieldForCreate(onlineAnnotationDO,new Date());
        log.info("text: ====> :{}，user=====> :{}", text, user);
        return onlineAnnotationDO;
    }

    private List<String> extractJsonTexts(String xml) {
        List<String> texts = new ArrayList<>();
        Matcher matcher = Pattern.compile("<MarkupJsonData[^>]+>(.+?)</MarkupJsonData>").matcher(xml);

        while (matcher.find()) {
            String json = matcher.group(1)
                    .replace("&quot;", "\"")  // 转换HTML实体
                    .replace("&#34;", "\"");   // 处理其他编码形式

            Matcher textMatcher = JSON_TEXT_PATTERN.matcher(json);
            if (textMatcher.find()) {
                texts.add(textMatcher.group(1));
            }
        }
        return texts;
    }

    private List<String> extractXmlContents(String xml) throws Exception {
        List<String> contents = new ArrayList<>();
        Document doc = DocumentBuilderFactory.newInstance()
                .newDocumentBuilder()
                .parse(new InputSource(new StringReader(xml)));

        XPath xpath = XPathFactory.newInstance().newXPath();
        NodeList nodes = (NodeList) xpath.evaluate(CONTENT_XPATH, doc, XPathConstants.NODESET);

        for (int i = 0; i < nodes.getLength(); i++) {
            String value = nodes.item(i).getNodeValue();
            if (!value.isEmpty()) {
                contents.add(value);
            }
        }
        return contents;
    }


    public Map<String, InputStream> getFileMap(HttpServletRequest request, PreviewParamDTO paramDTO) {
        try {
            List<PreviewFileInfoDTO> previewFiles = this.buildPreviewFile(paramDTO);
            Iterator var6 = previewFiles.iterator();
            Map<String, InputStream> fileMap = new HashMap<>();
            while(true) {
                PreviewFileInfoDTO previewFile;
                do {
                    if (!var6.hasNext()) {
                        return fileMap ;
                    }
                    previewFile = (PreviewFileInfoDTO)var6.next();
                } while(previewFiles.size() > 1 && (Objects.isNull(previewFile) || Objects.isNull(previewFile.getMainPreviewFile())));
                fileMap.putAll(this.buildDownUrlV2(request, paramDTO, previewFile));
            }
        } catch (Throwable var11) {
             throw new RuntimeException(var11);
        }
    }

    private @NotNull Map<String, InputStream> buildDownUrlV2(HttpServletRequest request, PreviewParamDTO paramDTO, PreviewFileInfoDTO previewFile) throws IOException {
        Map<String, InputStream> fileInputStreamMap = new HashMap<>();
        if (Boolean.TRUE.equals(this.isDwgFile(previewFile))) {
            String userId = this.judeUser(paramDTO.getUserId());
            PreviewPathDTO mainPreviewFile = previewFile.getMainPreviewFile();
            String foldName = TyplmFileDownloadUtils.folderName();
            String fileDownDir = TyplmFileDownloadUtils.fileRootPath() + foldName + File.separator;
            String fileName = mainPreviewFile.getFileName();
            this.typlmFileDownloadUtils.downFileToServer(mainPreviewFile.getFileId(), fileDownDir, fileName, userId);
            String filePath;
            if ("xls".equalsIgnoreCase(FileNameUtil.getSuffix(fileName))) {
                filePath = FileNameUtil.getPrefix(fileName);
                fileName = filePath + "." + "xlsx";
            }

            filePath = fileDownDir + fileName;
            FileInputStream fileInputStream = FileUtils.openInputStream(new File(filePath));
            fileInputStreamMap.put(fileName, fileInputStream);
        } else {
            fileInputStreamMap = this.typlmPreviewFileService.buildPreviewZipV2(request, paramDTO, Lists.newArrayList(previewFile), false);
        }

        return fileInputStreamMap;
    }

    private Boolean isDwgFile(PreviewFileInfoDTO previewFiles) {
        String fileName = previewFiles.getMainPreviewFile().getFileName();
        return fileName.toUpperCase(Locale.ROOT).endsWith("xlsx".toUpperCase(Locale.ROOT)) || fileName.toUpperCase(Locale.ROOT).endsWith("xls".toUpperCase(Locale.ROOT));
    }

    private String judeUser(String userId) {
        if (StringUtils.isBlank(userId)) {
            return String.valueOf(CommonUtil.getUser().getOid());
        } else {
            UserDO userDO = this.typlmUserService.queryUserByKey(new BigInteger(userId));
            if (Objects.isNull(userDO)) {
                throw new TyException(Collections.singletonList(new TyException(ResponseCodeEnum.BIZ_USER_NOT_FOUND, new String[]{userId})));
            } else {
                TyAccountContext.setUser(userDO);
                return String.valueOf(userDO.getOid());
            }
        }
    }

    private List<PreviewFileInfoDTO> buildPreviewFile(PreviewParamDTO paramDTO) {
        String objType = paramDTO.getObjType();
        TyplmPreviewFileApiService instanceService = this.getInstanceService(objType);
        List<PreviewFileInfoDTO> previewFiles = instanceService.buildPreviewFileInfoS(paramDTO);
        if (CollUtil.isEmpty(previewFiles)) {
            String displayName = CommonUtil.getEntityDisplayName(new CTyEntityBaseDO(
                    EntityBaseUtil.getOidByStr(paramDTO.getObjId(), BigInteger.ZERO), paramDTO.getObjType()));
            throw SystemErrorCodeEnum.PREVIEW_FILE_NOT_FOUND.getException(displayName);
        } else {
            return previewFiles;
        }
    }

    private TyplmPreviewFileApiService getInstanceService(String objType) {
        Class<?> objClass = PreviewFactory.getClassByoType(objType);
        if (Objects.isNull(objClass)) {
            throw new MessageException(SystemErrorCodeEnum.PREVIEW_NOT_FIND_INSTANCE, objType);
        } else {
            Object instance = SpringUtil.getBean(objClass);
            return (TyplmPreviewFileApiService)instance;
        }
    }

    public List<MultipartFile> extractZipToMultipartFiles(File tempZipFile) throws IOException {
        List<MultipartFile> files = new ArrayList<>();

        // 1. 创建 ZipInputStream 来读取 zip 文件
        try (FileInputStream fis = new FileInputStream(tempZipFile);
             ZipInputStream zis = new ZipInputStream(fis)) {

            ZipEntry entry;
            // 2. 逐个读取 zip 文件中的条目
            while ((entry = zis.getNextEntry()) != null) {
                // 如果是文件（而不是目录）
                if (!entry.isDirectory()) {
                    // 创建一个字节数组来保存当前文件内容
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int bytesRead;

                    // 读取当前条目内容
                    while ((bytesRead = zis.read(buffer)) != -1) {
                        byteArrayOutputStream.write(buffer, 0, bytesRead);
                    }

                    // 3. 将文件内容转为 MultipartFile
                    byte[] fileContent = byteArrayOutputStream.toByteArray();
                    MultipartFile multipartFile = new MockMultipartFile(entry.getName(), entry.getName(), "application/octet-stream", fileContent);

                    // 4. 将文件添加到集合中
                    files.add(multipartFile);
                }
                zis.closeEntry();
            }
        }

        return files;
    }



    @Override
    public void checkDocAndCadIbaValue(String workFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(
                new BigInteger(workFlowContainerId));
        if (workFlowContainerView instanceof WorkFlowObjectPackage) {
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<IdentifierEntity> cadFlowList = new ArrayList<>();
            List<IdentifierEntity> docFlowList = new ArrayList<>();
            Map<String, String> map = new HashMap<>();
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                for(FlowObject flowObject : flowObjectList){
                    String objectNumber = flowObject.getObjectNumber();
                    String refObjectOtype = flowObject.getRefObjectOtype();
                    if (TableTypeConstrant.TY_CADDOC_OTYPE.equals(refObjectOtype) ) {
                        map.put(flowObject.getRefObjectOid().toString(), objectNumber);
                        cadFlowList.add(new IdentifierEntity(flowObject.getRefObjectOid(), flowObject.getRefObjectOtype()));
                    }else if(TableTypeConstrant.TY_DOC_OTYPE.equals(refObjectOtype)){
                        map.put(flowObject.getRefObjectOid().toString(), objectNumber);
                        docFlowList.add(new IdentifierEntity(flowObject.getRefObjectOid(), flowObject.getRefObjectOtype()));
                    }
                }
            }

            List<BigInteger> cadOid = cadFlowList.stream().map(IdentifierEntity::getOid).collect(Collectors.toList());
            Map<String, List<AttributeVO>> cadIbaAttrValueByOidAndKeys = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                    cadOid, TableTypeConstrant.TY_CADDOC_OTYPE, Collections.singletonList("Stage"));

            List<BigInteger> docOid = docFlowList.stream().map(IdentifierEntity::getOid).collect(Collectors.toList());
            Map<String, List<AttributeVO>> docIbaAttrValueByOidAndKeys = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                    docOid, TableTypeConstrant.TY_DOC_OTYPE, Collections.singletonList("Stage"));
            cadIbaAttrValueByOidAndKeys.putAll(docIbaAttrValueByOidAndKeys);
            List<String> number = new ArrayList<>();
            for (Map.Entry<String, List<AttributeVO>> entry : cadIbaAttrValueByOidAndKeys.entrySet()) {
                String key = entry.getKey();
                List<AttributeVO> attrList = entry.getValue();
                if(CollUtil.isNotEmpty(attrList)){
                    AttributeVO attributeVO = attrList.get(0);
                    String attributeValue = attributeVO.getAttributeValue();
                    if(StringUtils.isNotBlank(attributeValue)){
                        if("A".equalsIgnoreCase(attributeValue) || "B".equalsIgnoreCase(attributeValue)){
                            number.add(map.get(key));
                        }
                    }
                }
            }
            if(!number.isEmpty()){
                throw RTErrorCodeEnum.DEV_CODE_EXIST.getException("对象:"+ String.join(",",number) + "不允许通过当前流程发布，请检查！");
            }
        }

    }

    @Override
    public void transitionStageCheck(String workFlowContainerId, String stage) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(
                new BigInteger(workFlowContainerId));
        if (workFlowContainerView instanceof WorkFlowObjectPackage) {
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<IdentifierEntity> cadFlowList = new ArrayList<>();
            List<IdentifierEntity> docFlowList = new ArrayList<>();
            Map<String, String> map = new HashMap<>();
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                for(FlowObject flowObject : flowObjectList){
                    String objectNumber = flowObject.getObjectNumber();
                    String refObjectOtype = flowObject.getRefObjectOtype();
                    if (TableTypeConstrant.TY_CADDOC_OTYPE.equals(refObjectOtype) ) {
                        map.put(flowObject.getRefObjectOid().toString(), objectNumber);
                        cadFlowList.add(new IdentifierEntity(flowObject.getRefObjectOid(), flowObject.getRefObjectOtype()));
                    }else if(TableTypeConstrant.TY_DOC_OTYPE.equals(refObjectOtype)){
                        map.put(flowObject.getRefObjectOid().toString(), objectNumber);
                        docFlowList.add(new IdentifierEntity(flowObject.getRefObjectOid(), flowObject.getRefObjectOtype()));
                    }
                }
            }

            List<BigInteger> cadOid = cadFlowList.stream().map(IdentifierEntity::getOid).collect(Collectors.toList());
            Map<String, List<AttributeVO>> cadIbaAttrValueByOidAndKeys = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                    cadOid, TableTypeConstrant.TY_CADDOC_OTYPE, Collections.singletonList("Stage"));

            List<BigInteger> docOid = docFlowList.stream().map(IdentifierEntity::getOid).collect(Collectors.toList());
            Map<String, List<AttributeVO>> docIbaAttrValueByOidAndKeys = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                    docOid, TableTypeConstrant.TY_DOC_OTYPE, Collections.singletonList("Stage"));
            cadIbaAttrValueByOidAndKeys.putAll(docIbaAttrValueByOidAndKeys);
            List<String> number = new ArrayList<>();
            List<String> numberIsStageNull = new ArrayList<>();
            for (Map.Entry<String, List<AttributeVO>> entry : cadIbaAttrValueByOidAndKeys.entrySet()) {
                String key = entry.getKey();
                List<AttributeVO> attrList = entry.getValue();
                if(CollUtil.isNotEmpty(attrList)){
                    AttributeVO attributeVO = attrList.get(0);
                    String attributeValue = attributeVO.getAttributeValue();
                    if(StringUtils.isNotBlank(attributeValue)){
                        if("A".equals(stage)){
                            if("A".equals(attributeValue) || "B".equals(attributeValue)){
                                number.add(map.get(key));
                            }
                        }else if("B".equals(stage)){
                            if("B".equals(attributeValue)){
                                number.add(map.get(key));
                            }
                        }
                    }else {
                        numberIsStageNull.add(map.get(key));
                    }
                }
            }
            List<String> errors = new ArrayList<>();
            if (!numberIsStageNull.isEmpty()) {
                errors.add("对象: " + String.join(",", numberIsStageNull) + " 阶段为空，请检查！");
            }
            if (!number.isEmpty()) {
                errors.add("对象: " + String.join(",", number) + " 不允许通过当前流程转阶段，请检查！");
            }
            // 统一抛出异常（如果有错误）
            if (!errors.isEmpty()) {
                throw RTErrorCodeEnum.DEV_CODE_EXIST.getException(String.join("; ", errors));
            }
        }

    }
}
